﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Infrastructure.CrossCutting.Checks;
using ITransaction = Data.Core.UoW.ITransaction;


namespace Infrastructure.Data.NH.Core.UoW
{
    public class NHTransaction : ITransaction
    {
        private bool disposed;
        private NHibernate.ITransaction transaction;

        public NHTransaction(NHibernate.ITransaction transaction)
        {
            Check.Against<ArgumentNullException>(transaction == null, "Expected a non null NHibernate.ITransaction instance");

            this.transaction = transaction;
        }

        #region Implementation of IDisposable

        /// <summary>
        /// Führt anwendungsspezifische Aufgaben aus, die mit dem Freigeben, Zurückgeben oder Zurücksetzen von nicht verwalteten Ressourcen zusammenhängen.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// Disposes off managed and un-managed resources used by the <see cref="NHTransaction"/> instnace.
        /// </summary>
        /// <param name="disposing"></param>
        private void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (!disposed)
                {
                    transaction.Dispose();
                    disposed = true;
                }
            }
        }

        #endregion

        #region Implementation of ITransaction

        public event EventHandler TransactionCommitted;
        public event EventHandler TransactionRolledback;

        /// <summary>
        /// Commits the changes made to the data store.
        /// </summary>
        /// <remarks>Implementors MUST raise the <see cref="ITransaction.TransactionCommitted"/> event.</remarks>
        public void Commit()
        {
            if (disposed)
                throw new ObjectDisposedException("NHTransaction", "Cannot commit a disposed transaction.");

            transaction.Commit();
            if (TransactionCommitted != null)
                TransactionCommitted(this, EventArgs.Empty);
        }

        /// <summary>
        /// Rollsback any changes made.
        /// </summary>
        /// <remarks>Implementors MUST raise the <see cref="ITransaction.TransactionRolledback"/> event.</remarks>
        public void Rollback()
        {
            if (disposed)
                throw new ObjectDisposedException("NHTransaction", "Cannot rollback a disposed transaction.");

            try
            {
                transaction.Rollback();
            }
            catch (NHibernate.TransactionException ex)
            {
                throw new Exception("Rollback failed", ex);
            }

            if (TransactionRolledback != null)
                TransactionRolledback(this, EventArgs.Empty);
        }

        #endregion
    }
}
